package com.lbm.baseclass.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.lbm.baseclass.dao.IBaseDAO;
import com.lbm.baseclass.model.BaseEntity;

public class BaseDAOImpl extends HibernateDaoSupport  implements IBaseDAO {

	protected final static Logger log = Logger.getLogger(BaseDAOImpl.class);
	@SuppressWarnings("rawtypes")
	@Override
	public List getValueObjectsByHQL(final String hql)throws DataAccessException {
		return getHibernateTemplate().find(hql);
	}
	@Override
	public void saveOrUpdateVO(BaseEntity vo) throws DataAccessException {
		getHibernateTemplate().saveOrUpdate(vo);
		
	}
	@SuppressWarnings("rawtypes")
	@Override
	public void saveOrUpdateBatchVO(List dataList) throws DataAccessException {
		getHibernateTemplate().saveOrUpdateAll(dataList);
		
	}
	@Override
	public void deleteVO(BaseEntity vo) throws DataAccessException {
		getHibernateTemplate().delete(vo);		
	}
	@SuppressWarnings("rawtypes")
	@Override
	public void deleteBatchVO(List dataList) throws DataAccessException {
		getHibernateTemplate().deleteAll(dataList);
		
	}
	public int getTotalNumBySQL(String sql, Object... args) throws DataAccessException {
		int amount = 0;
		final Session session = getSession(); // 取得session
		Query query = session.createSQLQuery("select count(*)  from (" + sql
				+ ") count_table"); // 查询符合条件数据
		for (int i = 0; i < args.length; i++) {
			query = query.setParameter(i, args[i]);
		}
		Object result = query.uniqueResult();
		amount = Integer.parseInt(result.toString());
		return amount;
	}
	@Override
	public int getDataTotalNum(String hql, Object... filter)
			throws DataAccessException {
		int amount = 0;
		final Session session = getSession(); // 取得session
		Query query = null;
		final int start = hql.toLowerCase().indexOf("from");
		query = session.createQuery("select count(*) from "
				+ hql.substring(start + 4)); // 查询符合条件数据
		for (int i = 0; i < filter.length; i++) {
			query = query.setParameter(i, filter[i]);

		}
		@SuppressWarnings("rawtypes")
		final List list = query.list();
		if (!list.isEmpty()) {
			amount = Integer.parseInt(list.get(0).toString());

		}
		releaseSession(session); // 关闭session

		return amount;
	}
	@SuppressWarnings("rawtypes")
	@Override
	public List getPageDataByHQL(String hql, int page_size, int pageNo,
			Object... args) throws DataAccessException {
		List list = new ArrayList();
		int total_page = 0; // 总页数

		final int total_num = getDataTotalNum(hql, args); // 总记录数
		if (total_num % page_size == 0) { // 取得总页数
			total_page = total_num / page_size;
		} else {
			total_page = total_num / page_size + 1;
		}
		if (pageNo > total_page)
			pageNo = total_page;
		final int start = (pageNo - 1) * page_size; // 开始数据的位置
		final int rowNum = page_size; // 每页显示数据
		// System.out.println("传递的参数为 "+obj);

		final Session session = getSession(); // 取得session
		Query query = null;
		query = session.createQuery(hql); // 查询符合条件的数据
		for (int i = 0; i < args.length; i++) {
			query = query.setParameter(i, args[i]);

		}
		query.setReadOnly(true); // 设置此连接为只读属性
		query.setFirstResult(start);
		query.setMaxResults(rowNum);

		list = query.list();
		releaseSession(session); // 关闭session

		return list;
	}
	public List<Map<String, Object>> queryForPagedListBySQL(String sql, int page, int rows, Object... args) throws DataAccessException {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		try {
			Connection conn = SessionFactoryUtils.getDataSource(getSessionFactory()).getConnection();
			PreparedStatement pstmt = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
			int index = 0;
			for (Object o : args) {
				pstmt.setObject(++index, o);
			}
			pstmt.setMaxRows(page * rows);
			ResultSet rs = pstmt.executeQuery();
			ResultSetMetaData meta = rs.getMetaData();
			int cols = meta.getColumnCount();
			int first = (page - 1) * rows;
			if (first == 0) {
				rs.beforeFirst();
			} else {
				rs.absolute(first);
			}
			while (rs.next()) {
				Map<String, Object> map = new HashMap<String, Object>();
				for (int i = 1; i <= cols; i++) {
					String key = meta.getColumnName(i);
					Object value = rs.getObject(i);
					if (value == null) value = "";
					map.put(key, value);
				}
				list.add(map);
			}
			pstmt.close();
			conn.close();
		} catch (SQLException e) {
			log.error(e);
		}
		return list;
	}
	@Override
	public List<Map<String, Object>> queryForListBySQL(String sql) throws DataAccessException {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		try {
			Connection conn = SessionFactoryUtils.getDataSource(getSessionFactory()).getConnection();
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet rs = pstmt.executeQuery();
			ResultSetMetaData meta = rs.getMetaData();
			int cols = meta.getColumnCount();
			while (rs.next()) {
				Map<String, Object> map = new HashMap<String, Object>();
				for (int i = 1; i <= cols; i++) {
					String key = meta.getColumnName(i);
					Object value = rs.getObject(i);
					if (value == null) value = "";
					map.put(key.toUpperCase(), value);
				}
				list.add(map);
			}
			pstmt.close();
			conn.close();
		} catch (SQLException e) {
			log.error(e);
		}
		return list;
	}
	@Override
	public void deleteVO(BaseEntity vo, String id) throws DataAccessException {
		getHibernateTemplate().delete(getVO(vo, id));
		
	}
	@Override
	public BaseEntity getVO(final BaseEntity vo, final String id)
			throws DataAccessException {
		final BaseEntity BaseEntity = getHibernateTemplate().get(vo.getClass(),
				id);

		if (BaseEntity == null) {
			throw new ObjectRetrievalFailureException(vo.getClass(), id);
		}

		return BaseEntity;

	}
	@Override
	public <T> T doInHibernate(HibernateCallback<T> callback) {
		return getHibernateTemplate().execute(callback);
	}
}
